<?php
/**
* Base of Packages
* 
* @package Smernel
*/
 
	class _smuoiPackage extends _smuoiDbObj{
		
		// Deafult rowclass may be set or left null
		protected $default_rowclass;
		
		var $db;
		
		protected $tables;
		
		protected $interface;
		
		protected $shutdown_commitees;
		
		function __construct($p, $db){
			$this->path = $p->path;
			$a = explode('/', $p->path);
			$this->name = array_shift($a);
			$this->version = implode('/', $a);
			$this->namespace = $p->namespace;
			$this->db = $db;
			$this->tables = $p->tables;
		}
		
		function get(){}
		
		function is_readable(){
			return true;	
		}
		
		function al(){
			return $this->db->open();	
		}
		
		function db(){
			return $this->db;	
		}
		
		function table($table){
			return $this->tables->$table->name;
		}
		
		function tableObj($table){
			return $this->tables->$table;
		}
		
		function key($table){
			return $this->tables->$table->key;
		}
		
		function cols($table){
			$table = $this->tableObj($table);
			if(!isset($table->cols)) $table->cols = $this->al()->tableCols($table->name);
			elseif(is_string($table->cols)) $table->cols = explode(',', $table->cols);
			return $table->cols;
		}
		
		function new_id($k){
			return $k.base_convert(utime(), 10, 36);
		}
		
		function new_id_on($ptable){
			return $this->new_id($this->key($ptable));
		}
		
		function apply_key($ptable, $id){
			return $this->key($ptable).$id;
		}
		
		function remove_key($id){
			return substr($id, $this->db->keylen());	
		}
		
		function apply_namespace($class){
			switch(substr($class, 0, 1)){
				case '~':
					return $this->namespace.'_'.substr($class, 1);
				default:
					return $this->namespace.'_'.$class;
			}
		}
		
		function remove_namespace($class){
			return substr($class, strlen($this->namespace)+1);
		}
		
		function path_to($arb=''){
			return PKG_DIR.'/'.$this->path."/$arb";
		}
		
		function path_to_dataclass($class){
			switch(substr($class, 0, 1)){
				case '~':
					return $this->domain()->getDir('desk').'/scripts/lib/'.substr($class, 1).'.php';
				default:
					return PKG_DIR.'/'.$this->path.'/DataClasses/'.$class.'.php';
			}
		}
		
		function path_to_libclass($class){
			return PKG_DIR.'/'.$this->path.'/Library/'.$class.'.php';
		}
		
		function test_instanceof($obj, $class){
			$class = $this->apply_namespace($class);
			return ($obj instanceof $class);
		}
		
		function is_valid_dataclass($class){
			return ((substr($class, 0, 1) !== '_')&&(is_file($this->path_to_dataclass($class))));
		}
		
		function classOf($data){
			return (@$data['class']) ? $data['class'] : $this->default_rowclass;
		}
		
		function instantiateRow($data, $res=false){
			if(!$class = $this->classOf($data)) return false;
			require_once $this->path_to_dataclass($class); 
			$class = $this->apply_namespace($class);
			return new $class($data['id'], $this, $data, $res);
		}
		
		function shutdown(){
			if(!$this->shutdown_commitees) return;
			while($obj = current($this->shutdown_commitees)){
				 $obj->commit();
				 next($this->shutdown_commitees);
			}
			// No reason the func should be called twice, but anyway...
			$this->shutdown_commitees = NULL;
		}
		
		function register_shutdown_commitee($obj){
			if(!$this->shutdown_commitees) smuoi_register_shutdown_function(array($this, 'shutdown'));
			$this->shutdown_commitees[$obj->id] = $obj;
		}
		
		function unregister_shutdown_commitee($obj){
			unset($this->shutdown_commitees[$obj->id]);
		}
		
		function userInterface($args=null){
			if(!is_null($this->interface)) return $this->interface;
			$uif = $this->path_to('Interface.php');
			if(!is_file($uif)) httpE(500, "Package $this->name has no User Interface");
			require_once $uif;
			$class = "Interface_".$this->namespace;
			$this->interface = new $class($this, $args);
			return $this->interface;
		}
	}

